package cn.zhfeat.framework.shiro.base;

import cn.zhfeat.utils.cache.CacheUtility;
import cn.zhfeat.framework.shiro.util.ShiroSerializeUtil;
import cn.zhfeat.utils.SerializeUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Set;

/**
 * @author ZhangHao
 * @version 1.0.0.1
 * @description: 结合redis缓存实现自己的cache
 * @date 2018年5月14日 上午11:15:53
 */
@SuppressWarnings("unchecked")
@Component
public class RedisCache<K, V> implements Cache<K, V> {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * @description: 包装的jedis实例
     *
     * @param
     * @author ZhangHao
     * @date 2018/10/22 14:50
     * @version 1.0.0.1
     * @return
     */

    private CacheUtility cacheUtility;

    private String categoryKey = "Shiro-Session";    //缓存类别
    private String cacheKey = "Permissions-Cache";        //缓存功能
    private String redisCacheListKey = "Shiro-System-UserId-"; //自定义的Cache List的key


    /**
     * @description: 登录会员的redis秘钥前缀
     *
     * @param
     * @author ZhangHao
     * @date 2018/10/22 14:50
     * @version 1.0.0.1
     * @return
     */

    private String keyPrefix = "redis_session_shiro:";

    /**
     * @description: 返回redis会话秘钥前缀
     *
     * @param
     * @author ZhangHao
     * @date 2018/10/22 14:51
     * @version 1.0.0.1
     * @return java.lang.String
     */

    public String getKeyPrefix() {
        return keyPrefix;
    }

    /**
     * @description: 设置redis会话秘钥前缀
     *
     * @param
     * @author ZhangHao
     * @date 2018/10/22 14:51
     * @version 1.0.0.1
     * @return void
     */

    public void setKeyPrefix(String keyPrefix) {
        this.keyPrefix = keyPrefix;
    }

    /**
     * @description: 通过一个JedisManager实例构造RedisCache
     *
     * @param
     * @author ZhangHao
     * @date 2018/10/22 14:52
     * @version 1.0.0.1
     * @return
     */

    public RedisCache(CacheUtility cacheUtility) {
        this.cacheUtility = cacheUtility;
    }

    /**
     * Constructs a cache instance with the specified
     * Redis manager and using a custom key prefix.
     *
     * @param cache  The cache manager instance
     * @param prefix The Redis key prefix
     */
//    public RedisCache(RedisManager cache,
//                      String prefix) {
//        this();
//        // set the prefix
//        this.keyPrefix = prefix;
//    }

    /**
     * @description: 获得byte[]型的key
     *
     * @param
     * @author ZhangHao
     * @date 2018/10/22 14:52
     * @version 1.0.0.1
     * @return byte[]
     */

    private byte[] getByteKey(K key) {
        if (key instanceof String) {
            String preKey = this.keyPrefix + key;
            return preKey.getBytes();
        } else {
            return SerializeUtils.serialize(key);
        }
    }

    @Override
    public V get(K key) throws CacheException {
        logger.debug("根据key从Redis中获取对象 key [" + key + "]");
        try {
            if (key == null) {
                return null;
            } else {
                String redisString = cacheUtility.getCacheDataManager().getStringValue(categoryKey, cacheKey, redisCacheListKey + key.toString());
                return (V) ShiroSerializeUtil.deserializeToObject(redisString);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public V put(K key, V value) throws CacheException {
        logger.debug("根据key从存储 key [" + key + "]");
        try {
            cacheUtility.getCacheDataManager().putStringValue(categoryKey, cacheKey, redisCacheListKey + key.toString(), ShiroSerializeUtil.serializeToString(value));
            return value;
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }

    @Override
    public V remove(K key) throws CacheException {
        logger.debug("从redis中删除 key [" + key + "]");
        try {
            V previous = get(key);
            cacheUtility.getCacheDataManager().removeValue(categoryKey, cacheKey, redisCacheListKey + key.toString());
            return previous;
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }

    @Override
    public void clear() throws CacheException {
        logger.debug("从redis中删除所有元素");
        try {
            // cache.flushDB();
            // TODO: 2018/5/20 删除所有元素
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }

    @Override
    public int size() {
        return 0;
    }

    @SuppressWarnings("unchecked")
    @Override
    public Set<K> keys() {
        return null;
    }

    @Override
    public Collection<V> values() {
        return null;
    }
}
